//
// Changelog:
//	- 28.02.2004: Created this file.
//	
// (C) 2004, Roberto Rossi
//
//
// To compile and execute this test utility 
// add: 
// 1) ICSharpCode.SharpZipLib.dll
// 2) ldapKeyFinder.dll
// 3) SharpPrivacyLibrary.dll
// to your project references.

using System;
using System.Collections;
using System.IO;
using SharpPrivacy;
using SharpPrivacy.OpenPGP;
using SharpPrivacy.OpenPGP.Messages;

namespace SharpPrivacy
{
	/// <summary>
	/// Descrizione di riepilogo per TestLibrary.
	/// </summary>
	public class TestLibrary
	{
		[STAThread]
		public static void Main (string[] args)
		{
			//Create the singleton instance of the cryptographyc service provider
			SharpPrivacyLibrary lib = SharpPrivacyLibrary.Instance;

			//Show Public and Private KeyRing Content
			System.Console.WriteLine("----------------------------------------------------------------------------");
			System.Console.WriteLine("Public KeyRing keys:");
			System.Console.WriteLine("----------------------------------------------------------------------------");
			foreach(TransportablePublicKey tpk in lib.PublicRing.PublicKeys)
			{
				System.Console.WriteLine(tpk.PrimaryUserID);
			}
			System.Console.WriteLine();
			System.Console.WriteLine("----------------------------------------------------------------------------");
			System.Console.WriteLine("Private KeyRing keys:");
			System.Console.WriteLine("----------------------------------------------------------------------------");
			foreach(TransportableSecretKey tsk in lib.SecretRing.SecretKeys)
			{
				foreach(UserIDPacket udp in tsk.UserIDs)
					System.Console.Write(udp.UserID+"   ");
				System.Console.Write("\n");
			}
			System.Console.WriteLine();
			System.Console.WriteLine("----------------------------------------------------------------------------");
			System.Console.WriteLine("LDAP Configuration:");
			System.Console.WriteLine("----------------------------------------------------------------------------");
			//Print current configuration of LDAP service
			System.Console.WriteLine("LDAP Service: ldap://" +SharpPrivacyLibrary.LdapKeyServer + ":" + SharpPrivacyLibrary.LdapPort);
			System.Console.WriteLine();
			System.Console.WriteLine("*****---------Sharp Privacy Library-----Debug 1.0-------*****");
			System.Console.WriteLine("*****-------------Testing command line utility----------*****");
			//Parsing input
			if(args.Length == 0)
			{
				printUsage();
				return;
			}
			System.Console.WriteLine("----------------------------------------------------------------------------");
			System.Console.WriteLine("Executing requested operation: ");
			System.Console.WriteLine("----------------------------------------------------------------------------");
			try
			{
				ArrayList encryptionKeys = null;
				TransportablePublicKey encryptionKey = null;
				TransportableSecretKey signingKey = null;
				string[] fileList = new string[1];
				string fileOut = "";

				string passphrase = "";
				string file = "";

				if(args[0] == "-e")
				{
					try
					{
						encryptionKey = (TransportablePublicKey)lib.PublicRing.FindPublicKeysByID(args[1])[0];
					}
					catch(Exception e)
					{
						string warn = e.Message;
						throw new Exception("Chiave pubblica non trovata");
					}
					encryptionKeys = new ArrayList();
					encryptionKeys.Add(encryptionKey);

					if(args[2] == "-s")
					{
						try
						{
							signingKey = (TransportableSecretKey)lib.SecretRing.FindSecretKeysByID(args[3])[0];
						}
						catch(Exception e)
						{
							string warn = e.Message;
							throw new Exception("Chiave privata non trovata");
						}
						if(args[4] == "-p")
						{
							passphrase = args[5];
						}
						file = args[6];
						fileList[0] = file;
						lib.EncryptFiles(fileList, signingKey, encryptionKeys,passphrase,true,true,true);
						return;
					}
					else
					{
						file = args[2];
						fileList[0] = file;
						lib.EncryptFiles(fileList, signingKey, encryptionKeys,"",true,false,true);
						return;
					}
				}
				else if(args[0] == "-s")
				{
					try
					{
						signingKey = (TransportableSecretKey)lib.SecretRing.FindSecretKeysByID(args[1])[0];
					}
					catch(Exception e)
					{
						string warn = e.Message;
						throw new Exception("Chiave privata non trovata");
					}
					if(args[2] == "-p")
					{
						passphrase = args[3];
					}
					file = args[4];
					fileList[0] = file;
					lib.EncryptFiles(fileList, signingKey, encryptionKeys,passphrase,false,true,bool.Parse(args[5]));
					return;
				}
				else if(args[0] == "-d")
				{
					file = args[1];
					if(args[2] == "-p")
					{
						passphrase = args[3];
						if(args[4] == "-o")
						{
							fileOut = args[5];
							string result = lib.DecryptAndVerifyFile(file,passphrase,fileOut);//,"decryptedAndVerified.txt");
							System.Console.WriteLine(result);
							return;
						}
					}
				}
				else if(args[0] == "-dv")
				{
					file = args[1];
					if(args[2] == "-p")
					{
						passphrase = args[3];
						if(args[4] == "-o")
						{
							fileOut = args[5];
							string result = lib.DecryptAndVerifyFile(file,passphrase,fileOut);//,"decryptedAndVerified.txt");
							System.Console.WriteLine(result);
							return;
						}
						if(args[6] == "-e")
						{
							fileOut = args[7];
							string result = lib.FileSignatureVerify(file,fileOut);//,"decryptedAndVerified.txt");
							System.Console.WriteLine(result);
							return;
						}
					}
				}
				else if(args[0] == "-v")
				{
					file = args[1];
					if(args[2] == "-o")
					{
						fileOut = args[3];
						string result = lib.DecryptAndVerifyFile(file,"",fileOut);//,"decryptedAndVerified.txt");
						System.Console.WriteLine(result);
						return;
					}
				}
				else if(args[0] == "-f")
				{
					string userID = args[1];
					ArrayList userKeys = lib.PublicRing.FindRemotePublicKeysByUserID(userID);
					System.Console.WriteLine();
					System.Console.WriteLine("KeyID      UserID");
					System.Console.WriteLine("-------------------------------------------------");
					foreach(string key in userKeys)
					{
						System.Console.WriteLine(key);
					}
					System.Console.WriteLine();
					System.Console.WriteLine("Hint: Narrow your search if no result is displayed (max result set to 100)");
					return;
				}
				else if(args[0] == "-fd")
				{
					string keyID = args[1];
					fileOut = args[2];
					string userKey = lib.PublicRing.FindRemotePublicKeyByKeyID(keyID);
					System.IO.FileStream fsOut = new FileStream(fileOut, FileMode.Create);
					System.IO.BinaryWriter bwOut = new BinaryWriter(fsOut);
					bwOut.Write(userKey);
					bwOut.Close();
					fsOut.Close();
					System.Console.WriteLine("Key retrieved.");
					return;
				}
				else if(args[0] == "-vk")
				{	
					string format = args[2];
					string userID = args[1];
					foreach(TransportablePublicKey tpk in lib.PublicRing.FindPublicKeysByID(userID))
					{
						System.Console.WriteLine("Verifying Key: "+tpk.PrimaryKey.KeyID.ToString(format));
						try
						{	
							System.Console.WriteLine("Expires on: "+tpk.KeyExpirationTime);
						}
						catch(Exception e)
						{
							System.Console.WriteLine("Expires on: " + e.Message);
						}
						System.Console.WriteLine("Revoked: " + lib.PublicRing.isRevoked(tpk.PrimaryKey.KeyID));
						foreach(CertifiedUserID cuid in tpk.Certifications)
						{
							System.Console.WriteLine("Certified user id: "+cuid.UserID.UserID+"  Primary: "+(cuid.UserID.UserID==tpk.PrimaryUserID)+"  Revoked: "+lib.PublicRing.isRevoked(tpk.PrimaryKey.KeyID,cuid.UserID.UserID,tpk.PrimaryKey.KeyID));
							foreach(SignaturePacket sp in cuid.Certificates )
							{
								if(sp.SignatureType == SignatureTypes.UserIDSignature ||
									sp.SignatureType == SignatureTypes.UserIDSignature_CasualVerification ||
									sp.SignatureType == SignatureTypes.UserIDSignature_NoVerification ||
									sp.SignatureType == SignatureTypes.UserIDSignature_PositivVerification)
								{
									System.Console.Write("\tsigner: "+sp.KeyID.ToString(format)+" "+lib.PublicRing.Find(sp.KeyID,true).PrimaryUserID+" Revoked: "+lib.PublicRing.isRevoked(tpk.PrimaryKey.KeyID,cuid.UserID.UserID,sp.KeyID));
									bool updated = false;
									foreach(SignatureSubPacket ssp in sp.HashedSubPackets)
									{
										if(ssp.Type == SignatureSubPacketTypes.TrustSignature)
										{
											System.Console.Write("Trust level: "+(int)ssp.TrustLevel + " Trust Amount: " + (int)ssp.TrustAmount);
											updated = true;
										}
									}
									if(!updated)
									{
										foreach(SignatureSubPacket ssp in sp.UnhashedSubPackets)
										{
											if(ssp.Type == SignatureSubPacketTypes.TrustSignature)
											{
												System.Console.Write("Trust level: "+(int)ssp.TrustLevel + " Trust Amount: " + (int)ssp.TrustAmount);
												updated = true;
											}
										}
									}
									System.Console.WriteLine();
								}
							}
						}
						ArrayList invalid = lib.PublicRing.verifySignatures(tpk.PrimaryKey.KeyID);
						foreach(CertifiedPublicSubkey cps in tpk.SubKeys)
						{
							try
							{
								System.Console.WriteLine("Found subkey: " + cps.Subkey.KeyID.ToString(format) + " Revoked: " + lib.PublicRing.isRevoked(cps.Subkey.KeyID) + " Expires on: " + cps.KeyBindingSignature.FindExpirationTime());
							}
							catch(Exception e)
							{
								String msg = e.Message;
								System.Console.WriteLine("Found subkey: " + cps.Subkey.KeyID.ToString(format) + " Revoked: " + lib.PublicRing.isRevoked(cps.Subkey.KeyID) + " Expires on: never");
							}
						}
						
						System.Console.WriteLine("Invalid Signs: " + invalid.Count);
						for(int x = 0; x < invalid.Count; x++)
						{
							if(invalid[x] is SignaturePacket)
							{
								SignaturePacket invalidSig = ((SignaturePacket)invalid[x]);
								System.Console.WriteLine("Signature by " + invalidSig.KeyID.ToString(format).ToUpper() + " " +invalidSig.SignatureStatus);
							}
							else if(invalid[x] is CertifiedUserID)
							{
								CertifiedUserID invalidSig = ((CertifiedUserID)invalid[x]);
								System.Console.WriteLine("Invalid User ID: " + invalidSig.UserID.UserID + " " + invalidSig.CertificationValidityStatus);
							}
							else if(invalid[x] is CertifiedPublicSubkey)
							{
								CertifiedPublicSubkey invalidSig = ((CertifiedPublicSubkey)invalid[x]);
								try
								{
									System.Console.WriteLine("Invalid Subkey: " + invalidSig.Subkey.KeyID.ToString(format).ToUpper() + " " + invalidSig.KeyBindingSignature.SignatureStatus);
								}
								catch(Exception e)
								{
									string msg = e.Message;
									System.Console.WriteLine("Invalid Subkey: " + invalidSig.Subkey.KeyID.ToString(format).ToUpper() + " Revoked");
								}
							}
						}
					}
					return;
				}
				else if(args[0] == "-genk")
				{
					lib.GenerateKey(Int32.Parse(args[1]),args[2],args[3],args[4],args[5],new DateTime(Int32.Parse(args[6]),Int32.Parse(args[7]),Int32.Parse(args[8])),Int32.Parse(args[11]),Boolean.Parse(args[9]),Boolean.Parse(args[10]));
					lib.PublicRing.Save();
					lib.SecretRing.Save();
					return;
				}
				else if(args[0] == "-gensk")
				{
					ulong id = ((TransportablePublicKey)lib.PublicRing.FindPublicKeysByID(args[3])[0]).PrimaryKey.KeyID;
					lib.GenerateSubkey(Int32.Parse(args[1]),args[2],id,new DateTime(Int32.Parse(args[6]),Int32.Parse(args[7]),Int32.Parse(args[8])),Boolean.Parse(args[9]));
					lib.PublicRing.Save();
					lib.SecretRing.Save();
					return;
				}
				else if(args[0] == "-adduid")
				{
					ulong id = ((TransportablePublicKey)lib.PublicRing.FindPublicKeysByID(args[5])[0]).PrimaryKey.KeyID;
					lib.AddUserID(args[1],args[2],args[3],args[4],id,Boolean.Parse(args[6]));
					lib.PublicRing.Save();
					lib.SecretRing.Save();
					return;
				}
				else if(args[0] == "-cpuid")
				{
					CertifiedUserID userID = null;
					ulong id = ulong.Parse(args[2]);
					foreach(CertifiedUserID cuid in lib.PublicRing.Find(id,false).Certifications)
					{
						if(cuid.UserID.UserID == args[1])
						{
							userID = cuid;
						}
					}
					if(userID != null)
					{
						lib.changePrimaryUserID(userID,id,args[3]);
					}
					else
						throw new Exception("UID not Found");
					lib.PublicRing.Save();
					lib.SecretRing.Save();
					return;
				}
				else if(args[0] == "-rkey")
				{
					ulong id = ((TransportablePublicKey)lib.PublicRing.FindPublicKeysByID(args[1])[0]).PrimaryKey.KeyID;
					TransportableSecretKey tskKey = ((TransportableSecretKey)lib.SecretRing.FindSecretKeysByID(args[2])[0]);
					lib.RevokeKey(id,tskKey,args[3],Boolean.Parse(args[4]));
					lib.PublicRing.Save();
					lib.SecretRing.Save();
					return;
				}
				else if(args[0] == "-rsubkey")
				{
					ulong id = (ulong)Int64.Parse(args[1]);
					TransportableSecretKey tskKey = ((TransportableSecretKey)lib.SecretRing.FindSecretKeysByID(args[2])[0]);
					lib.RevokeSubKey(id,tskKey,args[3],Boolean.Parse(args[4]));
					lib.PublicRing.Save();
					lib.SecretRing.Save();
					return;
				}
				else if(args[0] == "-rcert")
				{
					ulong id = ((TransportablePublicKey)lib.PublicRing.FindPublicKeysByID(args[1])[0]).PrimaryKey.KeyID;
					TransportablePublicKey key = ((TransportablePublicKey)lib.PublicRing.FindPublicKeysByID(args[1])[0]);
					TransportableSecretKey tskKey = ((TransportableSecretKey)lib.SecretRing.FindSecretKeysByID(args[3])[0]);
					foreach(CertifiedUserID cuid in key.Certifications)
					{
						if(cuid.UserID.UserID.IndexOf(args[2]) >= 0)
						{
							lib.RevokeKeyCertificate(id,cuid,tskKey,args[4],Boolean.Parse(args[5]));
							lib.PublicRing.Save();
							lib.SecretRing.Save();
							return;
						}
					}
				}
				else if(args[0] == "-sigk")
				{
					TransportablePublicKey signed = ((TransportablePublicKey)lib.PublicRing.FindPublicKeysByID(args[1])[0]);
					TransportableSecretKey tskKey = ((TransportableSecretKey)lib.SecretRing.FindSecretKeysByID(args[3])[0]);
					foreach(CertifiedUserID cuid in signed.Certifications)
					{
						if(cuid.UserID.UserID.IndexOf(args[2]) >= 0)
						{
							lib.SignKey(signed,cuid,tskKey,args[4],Boolean.Parse(args[5]),new DateTime(Int32.Parse(args[6]),Int32.Parse(args[7]),Int32.Parse(args[8])),Boolean.Parse(args[9]));
							lib.PublicRing.Save();
							lib.SecretRing.Save();
							return;
						}
					}
				}
				else if(args[0] == "-st")
				{
					TransportablePublicKey toBeTrusted = ((TransportablePublicKey)lib.PublicRing.FindPublicKeysByID(args[1])[0]);
					foreach(CertifiedUserID cuid in toBeTrusted.Certifications)
					{
						if(cuid.UserID.UserID.IndexOf(args[2]) >= 0)
						{
							lib.setUserIDTrust(toBeTrusted.PrimaryKey.KeyID,cuid,ulong.Parse(args[3]),args[4],Int32.Parse(args[5]),Int32.Parse(args[6]));
							lib.PublicRing.Save();
							lib.SecretRing.Save();
							return;
						}
					}
				}
				else if(args[0] == "-skp")
				{
					TransportablePublicKey tpkKey = ((TransportablePublicKey)lib.PublicRing.FindPublicKeysByID(args[1])[0]);
					TransportableSecretKey tskKey = ((TransportableSecretKey)lib.SecretRing.FindSecretKeysByID(args[1])[0]);
					if(tpkKey != null)
						lib.PublicRing.Save(args[2]+"_public.asc",tpkKey.PrimaryKey.KeyID);
					if(tskKey != null)
						lib.SecretRing.Save(args[2]+"_secret.asc",tskKey.PrimaryKey.PublicKey.KeyID);
					return;
				}
				System.Console.WriteLine("Invalid Input Option Error Occurred...\n");
				printUsage();
				return;
			}
			catch(Exception e)
			{
				System.Console.WriteLine(e.StackTrace);
				System.Console.WriteLine(e.Message+"\n");
				System.Console.WriteLine("An Error Occurred...\n");
				printUsage();
				return;
			}
			
/*
 *			LDAP using Active Directory --> IT DOES NOT WORK!!! SEE MICROSOFT REPORT ABOUT THE PROBLEM
 * 
			System.DirectoryServices.DirectoryEntry myDir = new System.DirectoryServices.DirectoryEntry("ldap://keyserver.pgp.com");
			string[] properties = new string[1];
			properties[0] = "pgpuserid";
			System.DirectoryServices.DirectorySearcher mySearcher = new System.DirectoryServices.DirectorySearcher(myDir,"(pgpuserid=*robertross@libero.it*)",properties);
			foreach(System.DirectoryServices.SearchResult result in mySearcher.FindAll()) 
			{
				Console.WriteLine( result.GetDirectoryEntry().Path );
			}
*/
		}

		public static void printUsage()
		{
			System.Console.WriteLine("----------------------------------------------------------------------------");
			System.Console.WriteLine("Usage of Sharp Privacy Library Command Line Tester \n(version beta 1.0): ");
			System.Console.WriteLine("----------------------------------------------------------------------------");
			System.Console.WriteLine("encrypt file: \t\t\t -e <PublicKeyUserID> <file>\n");
			System.Console.WriteLine("sign file: \t\t\t -s <PrivateKeyUserID> -p <password> <file> <embedMessage>\n");
			System.Console.WriteLine("encrypt & sign file: \t\t -e <PublicKeyUserID> -s <SecretKeyUserID> \n\t\t\t\t -p <password> <file>\n");
			System.Console.WriteLine("decrypt file: \t\t\t -d <file> -p <password> -o <fileOut>\n");
			System.Console.WriteLine("verify file:  \t\t\t -v <file> -o <fileOut>\n");
			System.Console.WriteLine("decrypt & verify file:  \t -dv <file> -p <password> -o <fileOut> -e <sigVerifyOut>\n");
			System.Console.WriteLine("verify extern signature:  \t -dv <file> -e <signatureFile>\n");
			System.Console.WriteLine("list remote keys by userID: \t -f <userID>\n");
			System.Console.WriteLine("get remote key by KeyID: \t -fd <PublicKeyID> <fileOut>\n");
			System.Console.WriteLine("save key pair: \t\t\t -skp <PublicKeyID> <fileOut>\n");
			System.Console.WriteLine("verify signature status: \t -vk <PublicKeyUserID> <format>\n");
			System.Console.WriteLine("generate key: \t\t\t -genk <keysize> <passphrase> <userID> <email> \n\t\t\t\t <notation> <expY> <expM> <expD> \n\t\t\t\t <isRevocableKey> <isRevocableSubkey> <keyType>\n");
			System.Console.WriteLine("generate sub key: \t\t -gensk <keysize> <passphrase> <keyPrimaryUID> \n\t\t\t\t <expY> <expM> <expD> <isRevocableSubkey>\n");
			System.Console.WriteLine("add userID: \t\t\t -adduid <userID> <email> <infos> <passphrase> \n\t\t\t\t <keyPrimaryUID> <isRevocable>\n");
			System.Console.WriteLine("change primary UID: \t\t -cpuid <newPrimaryUID> <keyID> <passphrase>\n");
			System.Console.WriteLine("revoke key: \t\t\t -rkey <keyPrimaryUID> <revokerPrimaryUID> \n\t\t\t\t <passphrase> <exportable>\n");
			System.Console.WriteLine("revoke subkey: \t\t\t -rskey <decimalkeyID> <revokerPrimaryUID> \n\t\t\t\t <passphrase> <exportable>\n");
			System.Console.WriteLine("revoke certificate: \t\t -rcert <keyPrimaryUID> <uidToRevoke> \n\t\t\t\t <revokerPrimaryUID> <passphrase> <exportable>\n");
			System.Console.WriteLine("sign key: \t\t\t -sigk <keyPrimaryUID> <uidToSign> \n\t\t\t\t <signerPrimaryUID> <passphrase> <exportable> \n\t\t\t\t <expY> <expM> <expD> <isRevocable>\n");
			System.Console.WriteLine("set trust: \t\t\t -st <PrimaryUIDKeyID> <keyPrimaryUID> \n\t\t\t\t <uidToTrust> <trusterKeyID> <passphrase> \n\t\t\t\t <trustLevel> <trustAmount>\n");
			System.Console.WriteLine();
			System.Console.WriteLine("----------------------------------------------------------------------------");
		}
	}
}
